/*
 * Copyright (c)  小马哥. 2022-2024. All rights reserved.
 *
 */

package com.phsms.common.sensitive.aspect;

import cn.hutool.core.util.StrUtil;
import com.phsms.common.sensitive.annotation.Desensitization;
import com.phsms.common.sensitive.annotation.DesensitizationProp;
import com.phsms.common.sensitive.configure.SensitiveProp;
import com.phsms.common.sensitive.util.MosDesensitizedUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;


/**
 * 切面
 * @author Mar
 * @date 2023年1月16日
 */
@Aspect
@Component
public class SensitiveAspect {
    @Resource
    private SensitiveProp sensitiveProp;

    public SensitiveAspect() {
    }

    @Pointcut("@annotation( com.phsms.common.sensitive.annotation.Desensitization)")
    public void getPoint() {
    }

    @Around("getPoint()")
    public Object sensitiveClass(ProceedingJoinPoint joinPoint) throws Throwable {
        if (!sensitiveProp.getEnable()) {
            return joinPoint.proceed();
        } else {
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            Desensitization desensitization = method.getAnnotation(Desensitization.class);
            return desensitization != null && desensitization.enable() ? this.sensitiveFormat(joinPoint) : joinPoint.proceed();
        }
    }

    public Object sensitiveFormat(ProceedingJoinPoint joinPoint) throws Throwable {
        Object obj = joinPoint.proceed();
        this.dealNode(obj);
        return obj;
    }

    private void dealList(Object o) throws IllegalAccessException {
        List<Object> list = (List)o;
        Iterator var3 = list.iterator();

        while(var3.hasNext()) {
            Object obj = var3.next();
            this.dealNode(obj);
        }

    }

    public void dealNode(Object o) throws IllegalAccessException {
        if (o instanceof List) {
            this.dealList(o);
        } else if (o != null) {
            boolean needDepthDeal = sensitiveProp.getDepth() && !StrUtil.isBlankIfStr(sensitiveProp.getPackages());
            Field[] fields = o.getClass().getDeclaredFields();
            Field[] var4 = fields;
            int var5 = fields.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                Field field = var4[var6];
                field.setAccessible(true);
                String type = field.getGenericType().toString();
                Object fieldValueObj = field.get(o);
                if (fieldValueObj instanceof List) {
                    this.dealList(fieldValueObj);
                }

                if (needDepthDeal && this.containType(type)) {
                    this.dealNode(fieldValueObj);
                }

                DesensitizationProp desensitizationProp = field.getAnnotation(DesensitizationProp.class);
                if (desensitizationProp != null) {
                    String v = MosDesensitizedUtil.desensitizeData(fieldValueObj, desensitizationProp);
                    field.set(o, v);
                }
            }

        }
    }

    private Boolean containType(String type) {
        String[] scanPackages = sensitiveProp.getPackages().split(",");
        boolean isContainType = false;
        String[] var4 = scanPackages;
        int var5 = scanPackages.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String scanPackage = var4[var6];
            if (type.contains(scanPackage)) {
                isContainType = true;
                break;
            }
        }

        return isContainType;
    }
}